package com.lzj.lock;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;

import com.lzj.utils.UnsafeInstance;

import sun.misc.Unsafe;

public class Lock {
	
	//用于线程竞争资源状态，能拿到状态继续执行，没拿到放进队列
	private volatile int state = 0;
	
	//当前获取了锁的线程
	private Thread lockHolder;
	
	//队列(保证入队出队的安全性)
	//ConcurrentLinkedDeque (是一个基于链接节点的无界线程安全队列，它采用先进先出的规则对节点进行排序，当我们添加一个元素的时候，它会添加到队列的尾部，当我们获取一个元素时，它会返回队列头部的元素)
	private final ConcurrentLinkedQueue<Thread> queue = new ConcurrentLinkedQueue<>();
	
	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	public Thread getLockHolder() {
		return lockHolder;
	}

	public void setLockHolder(Thread lockHolder) {
		this.lockHolder = lockHolder;
	}

	
	
//-----------------------------------------------------------------------------------------------	
	/**
	 *       所有线程一起抢state =0 ，只有为0时表示当前锁是自由的可以抢
	 *       多线程修改state只能保证一个线程成功，不能用synchronized关键字
	 *       采用无锁方式(CAS)
	 * CAS:指令执行的原子性
	 */
	//例如 T1 , T2 ,T3 三个线程
	//加锁具体实现
	public boolean aquire() {
		Thread current = Thread.currentThread();
		int state = getState();
		if(state == 0) {//当前线程可以加锁
			 //判断
			 ConcurrentLinkedQueue<Thread> q = this.queue;
			 //当一个线程进入后先判断队列中是否存在线程
			 if((q.size() == 0 || current == q.peek()) && compareAndSwapState(0, 1)) {
				 //判断队列size为0，并且CAS加锁，加锁成功，预期值为0，修改为1，表示加锁
				 //设置当前获取了锁的线程
				 setLockHolder(current);
				 return true;
			 }
		 }
		 return false;
	}
	
	//加锁
	public void lock() {
		if(aquire()) {
			//T1加锁成功
			//进入的线程加锁成功
			return;
		}
		//加锁失败执行：
		//当前线程
		Thread current = Thread.currentThread();
		//放入队列排队
		queue.add(current);
		//没有拿到锁的线程，自旋，直到被唤醒并加锁成功
		for(;;){
			//尝试进行加锁
			//T1释放锁，唤醒T2
			if((queue.peek() == current) && aquire()) {//拿队列第一个线程,去加锁
				queue.poll(); //加锁成功线程被唤醒，T2从队列移除
				return;
			}
			//拿锁再次失败，当前线程阻塞
			LockSupport.park();
			//--------------------------------------
			//超时情况
			//--------------------------------------
		}
	}
	
//-----------------------------------------------------------------------------------------------

	
//-----------------------------------------------------------------------------------------------
	
	//解锁
	public void unlock() {
		//当前线程
		Thread current = Thread.currentThread();
		//当前获取了锁的线程
		//判断当前线程不等于当前获取了锁的线程，是不可以释放锁的
		if(current != getLockHolder()) {
			throw new RuntimeException("不可以释放锁");
		}
		int c =getState();
		if(compareAndSwapState(1, 0)) {//释放锁，state从1改回0
			//当前获取了锁的线程制空
			setLockHolder(null);
			//唤醒队列中的队首线程
			Thread thread = queue.peek();
			if(thread != null) {
				LockSupport.unpark(thread);
			}
		}
	}

//-----------------------------------------------------------------------------------------------
	
	//CAS算法
	public final boolean compareAndSwapState(int expect , int update) {
		//参数说明
	    //1.修改对象
		//2.偏移量
		//3.预期初始值
		//4.修改后的值
		return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
	}
	
	//反射获取Unsafe类
	private static final Unsafe unsafe =UnsafeInstance.reflectGetUnsafe();
	
	//定义偏移量
	private static final long stateOffset;
	//偏移量计算
	static {
		try {
			stateOffset = unsafe.objectFieldOffset(Lock.class.getDeclaredField("state"));
		} catch (Exception e) {
			throw new Error();
		}
	}
	
}
